home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / osrc.arc / AX25.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-04-16  |  10.5 KB  |  414 lines

  1. /* Low level AX.25 frame processing - address header */
  2.  
  3. #include <stdio.h>
  4. #include "global.h"
  5. #include "mbuf.h"
  6. #include "iface.h"
  7. #include "timer.h"
  8. #include "arp.h"
  9. #include "slip.h"
  10. #include "ax25.h"
  11. #include "lapb.h"
  12. #include <ctype.h>
  13.  
  14. void arp_input(),beac_input();
  15. static int axsend();
  16. int ip_route(),psax25(),setpath();
  17. struct mbuf *htonax25();
  18. struct ax25_cb *find_ax25(),*cr_ax25(),*open_ax25();
  19. char *res_arp();
  20. struct mbuf *htonax25();
  21. extern int16 Axwindow;
  22. extern struct ax25_addr Nr_nodebc;
  23. static int16 ax25rhash();
  24.  
  25. /* AX.25 broadcast address: "QST-0" in shifted ascii */
  26. struct ax25_addr ax25_bdcst = {
  27.     'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1,
  28.     ('0'<<1) | E,
  29. };
  30. char Axbdcst[AXALEN];    /* Same thing, network format */
  31. struct ax25_addr Mycall;
  32. struct ax_route *Ax_routes[NAXROUTE];    /* Routing table header */
  33. int Digipeat = 1;    /* Controls digipeating */
  34. struct ax_route Ax_default;    /* Default interface */
  35.  
  36. /* Send IP datagrams across an AX.25 link */
  37. int
  38. ax_send(bp,iface,gateway,prec,del,tput,rel)
  39. struct mbuf *bp;
  40. struct iface *iface;
  41. int32 gateway;
  42. int prec;
  43. int del;
  44. int tput;
  45. int rel;
  46. {
  47.     char *hw_addr;
  48.     struct ax25_cb *axp;
  49.     struct ax25_addr destaddr;
  50.     struct mbuf *tbp;
  51.  
  52.     if((hw_addr = res_arp(iface,ARP_AX25,gateway,bp)) == NULLCHAR)
  53.         return 0;    /* Wait for address resolution */
  54.  
  55.     if(del || (!rel && (iface->flags == DATAGRAM_MODE))){
  56.         /* Use UI frame */
  57.         return (*iface->output)(iface,hw_addr,
  58.             iface->hwaddr,PID_IP,bp);
  59.     }
  60.     /* Reliability is needed; use I-frames in AX.25 connection */
  61.     memcpy(destaddr.call,hw_addr,ALEN);
  62.     destaddr.ssid = hw_addr[ALEN];
  63.  
  64.     if((axp = find_ax25(&destaddr)) == NULLAX25){
  65.         /* Open a new connection */
  66.         axp = open_ax25(iface,(struct ax25_addr *)iface->hwaddr,
  67.          (struct ax25_addr *)hw_addr,
  68.          Axwindow,s_arcall,s_atcall,s_ascall,-1);
  69.         if(axp == NULLAX25){
  70.             free_p(bp);
  71.             return -1;
  72.         }
  73.     }
  74.     if(axp->state == DISCONNECTED){
  75.         est_link(axp);
  76.         lapbstate(axp,SETUP);
  77.     }
  78.     /* Insert the PID */
  79.     if((tbp = pushdown(bp,1)) == NULLBUF){
  80.         free_p(bp);
  81.         return -1;
  82.     }
  83.     bp = tbp;
  84.     bp->data[0] = PID_IP;
  85.     tbp = segmenter(bp,axp->paclen);
  86.     return send_ax25(axp,tbp,-1);
  87. }
  88. /* Add AX.25 link header and send packet.
  89.  * Note that the calling order here must match enet_output
  90.  * since ARP also uses it.
  91.  */
  92. int
  93. ax_output(iface,dest,source,pid,data)
  94. struct iface *iface;    /* Interface to use; overrides routing table */
  95. char *dest;        /* Destination AX.25 address (7 bytes, shifted) */
  96. char *source;        /* Source AX.25 address (7 bytes, shifted) */
  97. int16 pid;        /* Protocol ID */
  98. struct mbuf *data;    /* Data field (follows PID) */
  99. {
  100.     struct mbuf *bp;
  101.  
  102.     /* Prepend pid to data */
  103.     bp = pushdown(data,1);
  104.     if(bp == NULLBUF){
  105.         free_p(data);
  106.         return -1;
  107.     }
  108.     bp->data[0] = (char)pid;
  109.     return axsend(iface,(struct ax25_addr *)dest,
  110.      (struct ax25_addr *)source,COMMAND,UI,bp);
  111. }
  112. /* Common subroutine for sendframe() and ax_output() */
  113. static int
  114. axsend(iface,dest,source,cmdrsp,ctl,data)
  115. struct iface *iface;    /* Interface to use; overrides routing table */
  116. struct ax25_addr *dest;    /* Destination AX.25 address (7 bytes, shifted) */
  117. struct ax25_addr *source;/* Source AX.25 address (7 bytes, shifted) */
  118. char cmdrsp;        /* Command/response indication */
  119. char ctl;        /* Control field */
  120. struct mbuf *data;    /* Data field (includes PID) */
  121. {
  122.     struct mbuf *cbp;
  123.     struct ax25 addr;
  124.     struct ax_route *axr;
  125.  
  126.     /* If there's a digipeater route, get it */
  127.     axr = ax_lookup((struct ax25_addr *)dest);
  128.  
  129.     memset((char *)&addr,0,sizeof(addr));
  130.     ASSIGN(addr.dest,*dest);
  131.     ASSIGN(addr.source,*source);
  132.     addr.cmdrsp = cmdrsp;
  133.  
  134.     if(axr != NULLAXR){
  135.         memcpy((char *)addr.digis,(char *)axr->digis,
  136.          axr->ndigis*sizeof(struct ax25_addr));
  137.         addr.ndigis = axr->ndigis;
  138.     } else
  139.         addr.ndigis = 0;
  140.  
  141.     /* Allocate mbuf for control field, and fill in */
  142.     if((cbp = pushdown(data,1)) == NULLBUF){
  143.         free_p(data);
  144.         return -1;
  145.     }
  146.     cbp->data[0] = ctl;
  147.  
  148.     if((data = htonax25(&addr,cbp)) == NULLBUF){
  149.         free_p(cbp);    /* Also frees data */
  150.         return -1;
  151.     }
  152.     /* This shouldn't be necessary because redirection has already been
  153.      * done at the IP router layer, but just to be safe...
  154.      */
  155.     if(iface->forw != NULLIF)
  156.         return (*iface->forw->raw)(iface->forw,data);
  157.     else
  158.         return (*iface->raw)(iface,data);
  159. }
  160. /* Process incoming AX.25 packets.
  161.  * After optional tracing, the address field is examined. If it is
  162.  * directed to us as a digipeater, repeat it.  If it is addressed to
  163.  * us or to QST-0, kick it upstairs depending on the protocol ID.
  164.  */
  165. int
  166. ax_recv(iface,bp)
  167. struct iface *iface;
  168. struct mbuf *bp;
  169. {
  170.     struct ax25_addr *ap;
  171.     struct mbuf *hbp;
  172.     char multicast;
  173.     int nrnodes = 0;
  174.     char control;
  175.     struct ax25 hdr;
  176.     struct ax25_cb *axp;
  177.     struct ax25_addr ifcall;
  178.     struct ax_route *axr;
  179.  
  180.     /* Use the address associated with this iface */
  181.     memcpy(ifcall.call,iface->hwaddr,ALEN);
  182.     ifcall.ssid = iface->hwaddr[ALEN];
  183.  
  184.     /* Pull header off packet and convert to host structure */
  185.     if(ntohax25(&hdr,&bp) < 0){
  186.         /* Something wrong with the header */
  187.         free_p(bp);
  188.         return;
  189.     }
  190.     /* Scan, looking for our call in the repeater fields, if any.
  191.      * Repeat appropriate packets.
  192.      */
  193.     for(ap = &hdr.digis[0]; ap < &hdr.digis[hdr.ndigis]; ap++){
  194.         if(ap->ssid & REPEATED)
  195.             continue;    /* Already repeated */
  196.         /* Check if packet is directed to us as a digipeater */
  197.         if(Digipeat && addreq(ap,&ifcall)){
  198.             /* Yes, kick it back out */
  199.             ap->ssid |= REPEATED;
  200.             if((hbp = htonax25(&hdr,bp)) != NULLBUF){
  201.                 if(iface->forw != NULLIF)
  202.                     (*iface->forw->raw)(iface->forw,hbp);
  203.                 else
  204.                     (*iface->raw)(iface,hbp);
  205.                 bp = NULLBUF;
  206.             }
  207.         }
  208.         free_p(bp);    /* Dispose if not forwarded */
  209.         return;
  210.     }
  211.     /* Packet has passed all repeaters, now look at destination */
  212.     if(addreq(&hdr.dest,&ax25_bdcst)){
  213.         multicast = 1;    /* Broadcast packet */
  214.     } else if(addreq(&hdr.dest,&ifcall)){
  215.         multicast = 0;    /* Packet directed at us */
  216.     } else if(addreq(&hdr.dest,&Nr_nodebc)){
  217.         nrnodes = 1 ;
  218.     } else {
  219.         /* Not for us */
  220.         free_p(bp);
  221.         return;
  222.     }
  223.     if(bp == NULLBUF){
  224.         /* Nothing left */
  225.         return;
  226.     }
  227.     /* Sneak a peek at the control field. This kludge is necessary because
  228.      * AX.25 lacks a proper protocol ID field between the address and LAPB
  229.      * sublayers; a control value of UI indicates that LAPB is to be
  230.      * bypassed.
  231.      */
  232.     control = *bp->data & ~PF;
  233.     if(uchar(control) == UI){
  234.         char pid;
  235.  
  236.         (void) pullchar(&bp);
  237.         if(pullup(&bp,&pid,1) != 1)
  238.             return;        /* No PID */
  239.         /* NET/ROM is very poorly layered. The meaning of the stuff
  240.          * following the PID of CF depends on what's in the AX.25 dest
  241.          * field.
  242.          */
  243.         if(nrnodes){
  244.             if(uchar(pid) == PID_NETROM)
  245.                 nr_nodercv(iface,&hdr.source,bp) ;
  246.             else     /* regular UI packets to "nodes" aren't for us */
  247.                 free_p(bp) ;
  248.             return ;
  249.         }
  250.         /* Handle packets. Multi-frame messages are not allowed */
  251.         switch(uchar(pid)){
  252.         case PID_IP:
  253.             ip_route(bp,multicast);
  254.             break;
  255.         case PID_ARP:
  256.             arp_input(iface,bp);
  257.             break;
  258.         case PID_NO_L3:
  259.             beac_input(iface,&hdr.source,bp);
  260.             break;
  261.         default:
  262.             free_p(bp);
  263.             break;
  264.         }
  265.         return;
  266.     }
  267.     /* Everything from here down is LAPB, so drop anything that's
  268.      * not explicitly for us ...
  269.      */
  270.     if (multicast || nrnodes) {
  271.         free_p(bp) ;
  272.         return ;
  273.     }
  274.     /* If there's no locally-set entry in the routing table,
  275.      * enter or update it. Leave local routes alone.
  276.      */
  277.     if((axr = ax_lookup(&hdr.source)) == NULLAXR || axr->type == AX_AUTO){
  278.         struct ax25_addr digis[MAXDIGIS];
  279.  
  280.         if(hdr.ndigis > 0){
  281.             int i,j;
  282.             /* Construct reverse digipeater path */
  283.             for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
  284.                 memcpy((char *)&digis[j],(char *)&hdr.digis[i],
  285.                     sizeof(struct ax25_addr));
  286.                 digis[j].ssid &= ~(E|REPEATED);
  287.             }
  288.         }
  289.         ax_add(&hdr.source,AX_AUTO,digis,hdr.ndigis);
  290.     }
  291.     /* Find the source address in hash table */
  292.     if((axp = find_ax25(&hdr.source)) == NULLAX25){
  293.         /* Create a new ax25 entry for this guy,
  294.          * insert into hash table keyed on his address,
  295.          * and initialize table entries
  296.          */
  297.         if((axp = cr_ax25(&hdr.source)) == NULLAX25){
  298.             free_p(bp);
  299.             return;
  300.         }
  301.         /* Swap source and destination */
  302.         ASSIGN(axp->remote,hdr.source);
  303.         ASSIGN(axp->local,hdr.dest);
  304.         axp->iface = iface;
  305.     }
  306.     if(hdr.cmdrsp == UNKNOWN)
  307.         axp->proto = V1;    /* Old protocol in use */
  308.  
  309.     lapb_input(axp,hdr.cmdrsp,bp);
  310. }
  311. /* General purpose AX.25 frame output */
  312. int
  313. sendframe(axp,cmdrsp,ctl,data)
  314. struct ax25_cb *axp;
  315. int cmdrsp;
  316. int ctl;
  317. struct mbuf *data;
  318. {
  319.     return axsend(axp->iface,&axp->remote,&axp->local,cmdrsp,ctl,data);
  320. }
  321. void
  322. axarp()
  323. {
  324.     memcpy(Axbdcst,ax25_bdcst.call,ALEN);
  325.     Axbdcst[ALEN] = ax25_bdcst.ssid;
  326.  
  327.     arp_init(ARP_AX25,AXALEN,PID_IP,PID_ARP,10,Axbdcst,psax25,setpath);
  328. }
  329. /* Find a route for an AX.25 address */
  330. struct ax_route *
  331. ax_lookup(target)
  332. struct ax25_addr *target;
  333. {
  334.     register struct ax_route *axr;
  335.  
  336.     for(axr = Ax_routes[ax25rhash(target)]; axr != NULLAXR; axr = axr->next){
  337.         if(addreq(&axr->target,target))
  338.             break;
  339.     }
  340.     return axr;
  341. }
  342. /* Add an entry to the AX.25 routing table */
  343. struct ax_route *
  344. ax_add(target,type,digis,ndigis)
  345. struct ax25_addr *target;
  346. int type;
  347. struct ax25_addr digis[];
  348. int ndigis;
  349. {
  350.     int16 hval,i;
  351.     register struct ax_route *axr;
  352.  
  353.     if(ndigis < 0 || ndigis > MAXDIGIS)
  354.         return NULLAXR;
  355.  
  356.     if((axr = ax_lookup(target)) == NULLAXR){
  357.         axr = (struct ax_route *)calloc(1,sizeof(struct ax_route));
  358.         if(axr == NULLAXR)
  359.             return NULLAXR;
  360.         hval = ax25rhash(target);
  361.         axr->prev = NULLAXR;
  362.         axr->next = Ax_routes[hval];
  363.         if(axr->next != NULLAXR)
  364.             axr->next->prev = axr;
  365.         Ax_routes[hval] = axr;
  366.         ASSIGN(axr->target,*target);
  367.         axr->ndigis = ndigis;
  368.     }
  369.     axr->type = type;
  370.     if(axr->ndigis != ndigis)
  371.         axr->ndigis = ndigis;
  372.  
  373.     for(i=0;i<ndigis;i++)
  374.         memcpy((char *)axr->digis,(char *)digis,
  375.          ndigis*sizeof(struct ax25_addr));
  376.     return axr;
  377. }
  378. int
  379. ax_drop(target)
  380. struct ax25_addr *target;
  381. {
  382.     register struct ax_route *axr;
  383.  
  384.     if((axr = ax_lookup(target)) == NULLAXR)
  385.         return -1;
  386.  
  387.     if(axr->next != NULLAXR)
  388.         axr->next->prev = axr->prev;
  389.     if(axr->prev != NULLAXR)
  390.         axr->prev->next = axr->next;
  391.     else
  392.         Ax_routes[ax25rhash(target)] = axr->next;
  393.     free((char *)axr);
  394.     return 0;
  395. }
  396. /* Address hash function. Exclusive-ORs each byte, ignoring
  397.  * such insignificant, annoying things as E and H bits
  398.  */
  399. static int16
  400. ax25rhash(s)
  401. struct ax25_addr *s;
  402. {
  403.     register char x;
  404.     register int i;
  405.     register char *cp;
  406.  
  407.     x = 0;
  408.     cp = s->call;
  409.     for(i=ALEN; i!=0; i--)
  410.         x ^= *cp++ & 0xfe;
  411.     x ^= s->ssid & SSID;
  412.     return uchar(x) % NAXROUTE;
  413. }
  414.